package de.akabahn.ebd.stw.zdxfc.prs.tco;

import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.BLOCK_1231_MELDER_AN;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_GLEIS_1;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_GLEIS_102;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_GLEIS_11;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_GLEIS_12;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_GLEIS_13;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_GLEIS_14;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_GLEIS_1BIS;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_GLEIS_2;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_GLEIS_2BIS;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_GLEIS_2TER;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_C1;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_C10;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_C2;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_C3;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_C8;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_CV11;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_CV12;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_CV13;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_CV14;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_CV4;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_CV5;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_CV6;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_CV7;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_CV9;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_SIGNAL_S4880;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_STRECKE_1231;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_1;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_10;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_110;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_12;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_2;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_3;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_4;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_5;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_6;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_7;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_8;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_WEICHE_9;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.SPERRE_ZDXFC;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.MELDER_GLEIS_15;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.MELDER_GLEIS_1617;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.SIGNAL_HALTMELDER_AUS;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.SIGNAL_HALTMELDER_C;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.SIGNAL_HALTMELDER_CV;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.WINDOW_SIZE_WIDTH;
import de.akabahn.ebd.dbd.DBDAdapter;
import de.akabahn.ebd.dbd.DBDSubscriptionListener;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.Gleis;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.Lampe;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.Signal;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.Weiche;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.signale.SignalImpair;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.signale.SignalPair;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche1;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche10;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche11;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche110;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche12;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche2;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche3;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche4;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche5;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche6;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche7;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche8;
import de.akabahn.ebd.stw.zdxfc.prs.tco.elemente.weichen.Weiche9;

/**
 * Initialisierung des TCO (beim Hochfahren), Setzen der verwendeten DBD-Variablen in den Grundzustand, 
 * Abonnieren der zu lesenden DBD-Variablen, Erstellung aller verwendeten Elemente
 * 
 * @author Peter Eimann
 * @since 1.0
 * @version 1.1
 * @see DBDSubscriptionListener
 */
public class ZDXFCTcoInitializer {

	private ZDXFCTcoMain main;
	private DBDSubscriptionListener listener;
	
	/**
	 * Initialisierung der Klasse
	 * 
	 * @param main Referenz auf die Hauptklasse
	 * @param listener Die DBD-Subscription Implementierung zum Abonnieren der Variablen
	 */
	public ZDXFCTcoInitializer(ZDXFCTcoMain main, DBDSubscriptionListener listener) {
		this.main = main;
		this.listener = listener;
	}

	/**
	 * Ausfuehrung der Initialisierung
	 * 
	 * @see #erstelleGleise()
	 * @see #erstelleWeichen()
	 * @see #erstelleSignale()
	 * @see #erstelleLampen()
	 */
	public void initialize() {
		erstelleGleise();
		erstelleWeichen();
		erstelleSignale();
		erstelleLampen();
	}
	
	/**
	 * Abonnieren der DBD-Variablen, deren Aenderung vom TCO ueberwacht werden sollen
	 * 
	 * @see #abonniereGleismelder()
	 * @see #abonniereWeichenGleismelder()
	 * @see #abonniereWeichenLagemelder()
	 * @see #abonniereSignalHaltmelder()
	 * @see #abonniereSignalVerschlussmelder()
	 * @see #abonniereLampen()
	 * @see #abonniereSperre()
	 */
	public void abonniereElemente() {
		abonniereGleismelder();
		abonniereWeichenGleismelder();
		abonniereWeichenLagemelder();
		abonniereSignalHaltmelder();
		abonniereSignalVerschlussmelder();
		abonniereLampen();
		abonniereSperre();
	}
	
	/**
	 * Erstellung der angezeigten Gleise
	 * 
	 * @see Gleis
	 * @see ZDXFCTcoMain#addGleis(Gleis)
	 */
	private void erstelleGleise() {
		main.addGleis(new Gleis(MELDER_GLEIS_2BIS, new int[]{70, 165}, new int[]{100, 100}, new int[]{65, 63}, new int[]{100, 190}));
		main.addGleis(new Gleis(MELDER_GLEIS_2, new int[]{452, 565}, new int[]{100, 100}, new int[]{63, 103}, new int[]{490, 590}));
		main.addGleis(new Gleis(MELDER_GLEIS_2TER, new int[]{792, 845}, new int[]{100, 100}, new int[]{23, 25}, new int[]{798, 853}));
		main.addGleis(new Gleis(MELDER_GLEIS_1BIS, new int[]{70, 165}, new int[]{150, 150}, new int[]{65, 63}, new int[]{100, 190}));
		main.addGleis(new Gleis(MELDER_GLEIS_1, new int[]{452, 565}, new int[]{150, 150}, new int[]{63, 103}, new int[]{490, 590}));
		main.addGleis(new Gleis(MELDER_GLEIS_102, new int[]{922, 1022}, new int[]{150, 150}, new int[]{38, 76}, new int[]{935, 1065}));
		main.addGleis(new Gleis(MELDER_STRECKE_1231, new int[]{1107, 1195}, new int[]{150, 150}, new int[]{58, 170}, new int[]{}));
		main.addGleis(new Gleis(MELDER_GLEIS_14, new int[]{70, 165}, new int[]{200, 200}, new int[]{65, 63}, new int[]{100, 190}));
		main.addGleis(new Gleis(MELDER_GLEIS_11, new int[]{382, 570}, new int[]{200, 200}, new int[]{133, 48}, new int[]{490, 590}));
		main.addGleis(new Gleis(MELDER_GLEIS_1617, new int[]{1092, 1130}, new int[]{200, 200}, new int[]{8, 10}, new int[]{}));
		main.addGleis(new Gleis(MELDER_GLEIS_12, new int[]{472, 570}, new int[]{250, 250}, new int[]{43, 48}, new int[]{490, 590}));
		main.addGleis(new Gleis(MELDER_GLEIS_15, new int[]{910, 955}, new int[]{250, 250}, new int[]{15, 13}, new int[]{}));
		main.addGleis(new Gleis(MELDER_GLEIS_13, new int[]{472, 570}, new int[]{300, 300}, new int[]{43, 48}, new int[]{490, 590}));
	}
	
	/**
	 * Erstellung der angezeigten Weichen
	 * 
	 * @see Weiche
	 * @see ZDXFCTcoMain#addWeiche(Weiche)
	 */
	private void erstelleWeichen() {
		main.addWeiche(new Weiche1());
		main.addWeiche(new Weiche2());
		main.addWeiche(new Weiche3());
		main.addWeiche(new Weiche4());
		main.addWeiche(new Weiche5());
		main.addWeiche(new Weiche6());
		main.addWeiche(new Weiche7());
		main.addWeiche(new Weiche8());
		main.addWeiche(new Weiche9());
		main.addWeiche(new Weiche10());
		main.addWeiche(new Weiche110());
		main.addWeiche(new Weiche11());
		main.addWeiche(new Weiche12());
	}
	
	/**
	 * Erstellung der angezeigten Signale
	 * 
	 * @see Signal
	 * @see ZDXFCTcoMain#addSignal(Signal)
	 */
	private void erstelleSignale() {
		main.addSignal(new SignalPair(MELDER_SIGNAL_C2, "C2",  1102, 150, SIGNAL_HALTMELDER_C, true, false));
		main.addSignal(new SignalPair(MELDER_SIGNAL_CV4, "Cv4", 917, 150, SIGNAL_HALTMELDER_CV, false, false));
		main.addSignal(new SignalPair(MELDER_SIGNAL_CV6, "Cv6", 1087, 200, SIGNAL_HALTMELDER_CV, false, false));
		main.addSignal(new SignalPair(MELDER_SIGNAL_C8, "C8", 447, 100, SIGNAL_HALTMELDER_C, false, false));
		main.addSignal(new SignalPair(MELDER_SIGNAL_C10, "C10", 447, 150, SIGNAL_HALTMELDER_C, false, false));
		main.addSignal(new SignalPair(MELDER_SIGNAL_CV12, "Cv12", 377, 250, SIGNAL_HALTMELDER_CV, false, false));
		main.addSignal(new SignalPair(MELDER_SIGNAL_CV14, "Cv14", 787, 100, SIGNAL_HALTMELDER_CV, false, false));
		
		main.addSignal(new SignalImpair(MELDER_SIGNAL_C1, "C1",  672, 100, SIGNAL_HALTMELDER_C, false, true));
		main.addSignal(new SignalImpair(MELDER_SIGNAL_C3, "C3",  672, 150, SIGNAL_HALTMELDER_C, false, true));
		main.addSignal(new SignalImpair(MELDER_SIGNAL_CV5, "Cv5",  782, 250, SIGNAL_HALTMELDER_CV, false, true));
		main.addSignal(new SignalImpair(MELDER_SIGNAL_CV7, "Cv7",  232, 100, SIGNAL_HALTMELDER_CV, false, false));
		main.addSignal(new SignalImpair(MELDER_SIGNAL_CV9, "Cv9",  232, 150, SIGNAL_HALTMELDER_CV, false, false));
		main.addSignal(new SignalImpair(MELDER_SIGNAL_CV11, "Cv11",  232, 200, SIGNAL_HALTMELDER_CV, false, false));
		main.addSignal(new SignalImpair(MELDER_SIGNAL_CV13, "Cv13",  972, 250, SIGNAL_HALTMELDER_CV, false, false));
		main.addSignal(new SignalImpair(MELDER_SIGNAL_S4880, "S488", 1040, 150, null, false, false));
	}
	
	/**
	 * Erstellung der angezeigten Lampen
	 * 
	 * @see Lampe
	 * @see ZDXFCTcoMain#addLampe(Lampe)
	 */
	private void erstelleLampen() {
		main.addLampe(new Lampe(BLOCK_1231_MELDER_AN, WINDOW_SIZE_WIDTH - 64, 105, SIGNAL_HALTMELDER_AUS, SIGNAL_HALTMELDER_C));
	}
	
	/**
	 * Abonniere die verwendeten Gleismelder (Ausleuchtung)
	 * @see DBDAdapter#subscribe(String, DBDSubscriptionListener)
	 */
	private void abonniereGleismelder() {
		main.getDbd().subscribe(MELDER_GLEIS_1, listener);
		main.getDbd().subscribe(MELDER_GLEIS_11, listener);
		main.getDbd().subscribe(MELDER_GLEIS_12, listener);
		main.getDbd().subscribe(MELDER_GLEIS_13, listener);
		main.getDbd().subscribe(MELDER_GLEIS_14, listener);
		main.getDbd().subscribe(MELDER_GLEIS_1BIS, listener);
		main.getDbd().subscribe(MELDER_GLEIS_102, listener);
		main.getDbd().subscribe(MELDER_GLEIS_2, listener);
		main.getDbd().subscribe(MELDER_GLEIS_2BIS, listener);
		main.getDbd().subscribe(MELDER_GLEIS_2TER, listener);
	}
	
	/**
	 * Abonniere die verwendeten Weichen-Gleismelder (Ausleuchtung)
	 * @see DBDAdapter#subscribe(String, DBDSubscriptionListener)
	 */
	private void abonniereWeichenGleismelder() {
		main.getDbd().subscribe(MELDER_WEICHE_1[0], listener);
		main.getDbd().subscribe(MELDER_WEICHE_2[0], listener);
		main.getDbd().subscribe(MELDER_WEICHE_3[0], listener);
		main.getDbd().subscribe(MELDER_WEICHE_4[0], listener);
		main.getDbd().subscribe(MELDER_WEICHE_5[0], listener);
		main.getDbd().subscribe(MELDER_WEICHE_6[0], listener);
		main.getDbd().subscribe(MELDER_WEICHE_7[0], listener);
		main.getDbd().subscribe(MELDER_WEICHE_8[0], listener);
		main.getDbd().subscribe(MELDER_WEICHE_9[0], listener);
		main.getDbd().subscribe(MELDER_WEICHE_10[0], listener);
		main.getDbd().subscribe(MELDER_WEICHE_110[0], listener);
		main.getDbd().subscribe(MELDER_WEICHE_12[0], listener);
	}
	
	/**
	 * Abonniere die verwendeten Weichen-Lagemelder (Ausleuchtung)
	 * @see DBDAdapter#subscribe(String, DBDSubscriptionListener)
	 */
	private void abonniereWeichenLagemelder() {
		main.getDbd().subscribe(MELDER_WEICHE_1[1], listener);
		main.getDbd().subscribe(MELDER_WEICHE_2[1], listener);
		main.getDbd().subscribe(MELDER_WEICHE_3[1], listener);
		main.getDbd().subscribe(MELDER_WEICHE_4[1], listener);
		main.getDbd().subscribe(MELDER_WEICHE_5[1], listener);
		main.getDbd().subscribe(MELDER_WEICHE_6[1], listener);
		main.getDbd().subscribe(MELDER_WEICHE_7[1], listener);
		main.getDbd().subscribe(MELDER_WEICHE_8[1], listener);
		main.getDbd().subscribe(MELDER_WEICHE_9[1], listener);
		main.getDbd().subscribe(MELDER_WEICHE_10[1], listener);
		main.getDbd().subscribe(MELDER_WEICHE_110[1], listener);
		main.getDbd().subscribe(MELDER_WEICHE_12[1], listener);
	}

	/**
	 * Abonniere die verwendeten Signal-Haltmelder (Ausleuchtung)
	 * @see DBDAdapter#subscribe(String, DBDSubscriptionListener)
	 */
	private void abonniereSignalHaltmelder() {
		main.getDbd().subscribe(MELDER_SIGNAL_C1[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_C2[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_C3[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_CV4[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_CV5[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_CV6[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_CV7[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_C8[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_CV9[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_C10[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_CV11[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_CV12[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_CV13[0], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_CV14[0], listener);
	}
	
	/**
	 * Abonniere die verwendeten Signal-Verschlussmelder (Ausleuchtung)
	 * @see DBDAdapter#subscribe(String, DBDSubscriptionListener)
	 */
	private void abonniereSignalVerschlussmelder() {
		main.getDbd().subscribe(MELDER_SIGNAL_C1[1], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_C2[1], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_C3[1], listener);
		main.getDbd().subscribe(MELDER_SIGNAL_CV5[1], listener);
	}
	
	/**
	 * Abonniere die verwendeten Lampen (Ausleuchtung)
	 * @see DBDAdapter#subscribe(String, DBDSubscriptionListener)
	 */
	private void abonniereLampen() {
		main.getDbd().subscribe(BLOCK_1231_MELDER_AN, listener);
	}

	/**
	 * Abonniere das Sperr-Flag
	 * @see DBDAdapter#subscribe(String, DBDSubscriptionListener)
	 */
	private void abonniereSperre() {
		main.getDbd().subscribe(SPERRE_ZDXFC, listener);
	}
}
